package com.gongyinlian.personalprofilewebsiteserver.controller;

import com.gongyinlian.personalprofilewebsiteserver.common.result.Result;
import com.gongyinlian.personalprofilewebsiteserver.utils.JwtUtil;
import com.gongyinlian.personalprofilewebsiteserver.utils.PasswordUtil;
import io.jsonwebtoken.Claims;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * JWT 测试控制器
 * 用于测试JWT工具类和密码工具类
 * 
 * @author personal-profile-website
 * @date 2024-10-27
 */
@Tag(name = "JWT测试接口", description = "测试JWT工具类和密码加密功能")
@RestController
@RequestMapping("/test/jwt")
@RequiredArgsConstructor
public class JwtTestController {
    
    private final JwtUtil jwtUtil;
    
    /**
     * 测试生成 Token
     */
    @Operation(summary = "生成Token", description = "测试Token生成功能")
    @GetMapping("/generate")
    public Result<Map<String, Object>> generateToken(
            @RequestParam(defaultValue = "1") Long userId,
            @RequestParam(defaultValue = "admin") String username) {
        
        String token = jwtUtil.generateToken(userId, username);
        String refreshToken = jwtUtil.generateRefreshToken(userId);
        
        Map<String, Object> data = new HashMap<>();
        data.put("accessToken", token);
        data.put("refreshToken", refreshToken);
        data.put("tokenType", "Bearer");
        data.put("expiresIn", jwtUtil.getTokenRemainingTime(token));
        
        return Result.success("Token生成成功", data);
    }
    
    /**
     * 测试解析 Token
     */
    @Operation(summary = "解析Token", description = "测试Token解析功能")
    @GetMapping("/parse")
    public Result<Map<String, Object>> parseToken(@RequestParam String token) {
        Claims claims = jwtUtil.getClaimsFromToken(token);
        
        if (claims == null) {
            return Result.error("Token解析失败");
        }
        
        Map<String, Object> data = new HashMap<>();
        data.put("userId", jwtUtil.getUserIdFromToken(token));
        data.put("username", jwtUtil.getUsernameFromToken(token));
        data.put("issuedAt", claims.getIssuedAt());
        data.put("expiration", claims.getExpiration());
        data.put("isExpired", jwtUtil.isTokenExpired(token));
        data.put("remainingTime", jwtUtil.getTokenRemainingTime(token));
        data.put("allClaims", claims);
        
        return Result.success("Token解析成功", data);
    }
    
    /**
     * 测试验证 Token
     */
    @Operation(summary = "验证Token", description = "测试Token验证功能")
    @GetMapping("/validate")
    public Result<Map<String, Object>> validateToken(@RequestParam String token) {
        boolean isValid = jwtUtil.validateToken(token);
        boolean isExpired = jwtUtil.isTokenExpired(token);
        
        Map<String, Object> data = new HashMap<>();
        data.put("isValid", isValid);
        data.put("isExpired", isExpired);
        data.put("remainingTime", jwtUtil.getTokenRemainingTime(token));
        
        if (isValid) {
            data.put("userId", jwtUtil.getUserIdFromToken(token));
            data.put("username", jwtUtil.getUsernameFromToken(token));
        }
        
        return Result.success(isValid ? "Token有效" : "Token无效", data);
    }
    
    /**
     * 测试从请求头获取 Token
     */
    @Operation(summary = "从请求头获取Token", description = "测试从Authorization头获取Token")
    @GetMapping("/from-header")
    public Result<Map<String, Object>> getTokenFromHeader(HttpServletRequest request) {
        String token = jwtUtil.getTokenFromRequest(request);
        
        Map<String, Object> data = new HashMap<>();
        data.put("token", token);
        
        if (token != null) {
            data.put("isValid", jwtUtil.validateToken(token));
            data.put("userId", jwtUtil.getUserIdFromToken(token));
            data.put("username", jwtUtil.getUsernameFromToken(token));
        }
        
        return Result.success(token != null ? "Token获取成功" : "未找到Token", data);
    }
    
    /**
     * 测试刷新 Token
     */
    @Operation(summary = "刷新Token", description = "测试Token刷新功能")
    @GetMapping("/refresh")
    public Result<Map<String, Object>> refreshToken(@RequestParam String token) {
        if (!jwtUtil.canTokenBeRefreshed(token)) {
            return Result.error("Token无法刷新（可能已过期）");
        }
        
        String newToken = jwtUtil.refreshToken(token);
        
        Map<String, Object> data = new HashMap<>();
        data.put("oldToken", token);
        data.put("newToken", newToken);
        data.put("expiresIn", jwtUtil.getTokenRemainingTime(newToken));
        
        return Result.success("Token刷新成功", data);
    }
    
    /**
     * 测试密码加密
     */
    @Operation(summary = "密码加密", description = "测试BCrypt密码加密")
    @GetMapping("/password/encode")
    public Result<Map<String, Object>> encodePassword(@RequestParam String password) {
        if (!PasswordUtil.isValidPassword(password)) {
            return Result.error("密码格式不正确（长度6-32位，不含空格）");
        }
        
        String encodedPassword = PasswordUtil.encode(password);
        int strength = PasswordUtil.getPasswordStrength(password);
        
        Map<String, Object> data = new HashMap<>();
        data.put("rawPassword", password);
        data.put("encodedPassword", encodedPassword);
        data.put("strength", strength);
        data.put("strengthDesc", strength == 0 ? "弱" : (strength == 1 ? "中" : "强"));
        
        return Result.success("密码加密成功", data);
    }
    
    /**
     * 测试密码验证
     */
    @Operation(summary = "密码验证", description = "测试密码验证功能")
    @GetMapping("/password/verify")
    public Result<Map<String, Object>> verifyPassword(
            @RequestParam String rawPassword,
            @RequestParam String encodedPassword) {
        
        boolean matches = PasswordUtil.matches(rawPassword, encodedPassword);
        
        Map<String, Object> data = new HashMap<>();
        data.put("rawPassword", rawPassword);
        data.put("encodedPassword", encodedPassword);
        data.put("matches", matches);
        
        return Result.success(matches ? "密码匹配" : "密码不匹配", data);
    }
    
    /**
     * 测试生成随机密码
     */
    @Operation(summary = "生成随机密码", description = "生成指定长度的随机密码")
    @GetMapping("/password/random")
    public Result<Map<String, Object>> generateRandomPassword(
            @RequestParam(defaultValue = "12") int length) {
        
        if (length < 6) {
            length = 6;
        }
        if (length > 32) {
            length = 32;
        }
        
        String randomPassword = PasswordUtil.generateRandomPassword(length);
        int strength = PasswordUtil.getPasswordStrength(randomPassword);
        
        Map<String, Object> data = new HashMap<>();
        data.put("password", randomPassword);
        data.put("length", randomPassword.length());
        data.put("strength", strength);
        data.put("strengthDesc", strength == 0 ? "弱" : (strength == 1 ? "中" : "强"));
        
        return Result.success("随机密码生成成功", data);
    }
    
    /**
     * 测试密码强度检测
     */
    @Operation(summary = "密码强度检测", description = "检测密码强度")
    @GetMapping("/password/strength")
    public Result<Map<String, Object>> checkPasswordStrength(@RequestParam String password) {
        int strength = PasswordUtil.getPasswordStrength(password);
        boolean isValid = PasswordUtil.isValidPassword(password);
        
        Map<String, Object> data = new HashMap<>();
        data.put("password", password);
        data.put("strength", strength);
        data.put("strengthDesc", strength == 0 ? "弱" : (strength == 1 ? "中" : "强"));
        data.put("isValid", isValid);
        data.put("length", password.length());
        data.put("hasNumber", password.matches(".*\\d+.*"));
        data.put("hasLowerCase", password.matches(".*[a-z]+.*"));
        data.put("hasUpperCase", password.matches(".*[A-Z]+.*"));
        data.put("hasSpecialChar", password.matches(".*[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>/?]+.*"));
        
        return Result.success("密码强度检测完成", data);
    }
}

